/**
 * 
 */
package com.netscenery.yang.model;

import java.util.ArrayList;

import org.jdom2.Attribute;
import org.jdom2.Element;

import com.netscenery.util.ErrTag;
import com.netscenery.util.QName;
import com.netscenery.util.XMLTag;
import com.netscenery.yang.YangKeyword;
import com.netscenery.yang.YangStatement;
import com.netscenery.yang.designer.MapInfo;
import com.netscenery.yang.parser.YangParserException;

/**
 * @author yanzi
 *
 */
public class Deviation extends ModelElement {
	private String description;
	private String reference;
	private ArrayList<Deviate> deviates;

	/**
	 * 
	 */
	public Deviation() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean checkName(String name) {
		
		return ModelElement.isAbsolutePath(env,name);
	}

	/**
	 * @param env
	 * @param name
	 * @throws ModelException 
	 */
	public Deviation(Env env, String name) throws ModelException {
		super(env, name);
		Node node = ModelElement.getNodeByAbsPath(env, name);
		if (null != node){
			env.setCurNode(node);
		}
		else {
			throw new ModelException(ErrTag.ERROR,"Invalid target node.");
		}
		return;
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param env
	 * @param qname
	 */
	public Deviation(Env env, QName qname) {
		super(env, qname);
		// TODO Auto-generated constructor stub
	}

	
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getReference() {
		return reference;
	}

	public void setReference(String reference) {
		this.reference = reference;
	}
	/**
	 * ��ȡdeviate����Ŀ
	 * @return
	 * @see com.netscenery.model.Deviate
	 */
	public int getDeviatesNumber(){
		if (null == this.deviates){
			return 0;
		}
		return this.deviates.size();
	}
	/**
	 * ���ָ������ƴ���deviates
	 * @param name
	 * @return
	 * @throws ModelException 
	 * @see com.netscenery.model.Deviate
	 */
	public Deviate createDeviate(String name) throws ModelException{
		if (null == name){
			return null;
		}
		
		return new Deviate(newSubEnv(),name);
	}
	/**
	 * ���һ��Deviate
	 * @param n
	 * @return
	 * @see com.netscenery.model.Deviate
	 */
	public boolean addDeviate(Deviate n){
		if(null == n){
			return false;
		}
		
		if (null == this.deviates){
			this.deviates = new ArrayList<Deviate>(1);
		}

		return this.deviates.add(n);
		

	}
	/**
	 * �����Ż�ȡDeviate
	 * @param index
	 * @return
	 * @see com.netscenery.model.Deviate
	 */
	public Deviate getDeviate(int index){
		if (null == this.deviates){
			return null;
		}
		if (index >= this.deviates.size()){
			return null;
		}
		return this.deviates.get(index);
	}

	/**
	 * ������ɾ��Deviate
	 * @param index
	 * @return Deviate
	 * @see com.netscenery.model.Deviate
	 */
	public Deviate removeDeviate(int index){
		if (null == this.deviates){
			return null;
		}
		if (index >= this.deviates.size()){
			return null;
		}
		return this.deviates.remove(index);
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYang()
	 */
	@Override
	public YangStatement toYang() {
		YangStatement statement = new YangStatement(YangStatement.YANG_STATEMENT_DEVIATION,this.name);
		if (null != this.description){
			YangStatement descr = new YangStatement(YangStatement.YANG_STATEMENT_DESCRIPTION,this.description);
			statement.addChild(descr);
		}
		if (null != this.reference){
			YangStatement ref = new YangStatement(YangStatement.YANG_STATEMENT_REFERENCE,this.getReference());
			statement.addChild(ref);
		}
		
		if (0 != getDeviatesNumber()){
			int size = getDeviatesNumber();
			for (int i = 0; i<size; i++){
				Deviate dev = getDeviate(i);
				if (null != dev){
					YangStatement devStatement = dev.writeYang();
					if (null != devStatement){
						statement.addChild(devStatement);
					}
				}
			}
		}
		return statement;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYin()
	 */
	@Override
	public Element toYin() {
		Element element = new Element(YangKeyword.DEVIATION.getKeyword(),env.getNs());
		Attribute target = new Attribute("target-node",this.name);
		element.setAttribute(target);
		
		if (null != this.description){
			Element descr = new Element(YangStatement.YANG_STATEMENT_DESCRIPTION,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.description);
			descr.addContent(text);
			element.addContent(descr);
		}
		if (null != this.reference){
			Element ref = new Element(YangStatement.YANG_STATEMENT_REFERENCE,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.reference);
			ref.addContent(text);
			element.addContent(ref);
		}
		
		if (0 != getDeviatesNumber()){
			int size = getDeviatesNumber();
			for (int i = 0; i<size; i++){
				Deviate dev = getDeviate(i);
				if (null != dev){
					Element devStatement = dev.writeYin();
					if (null != devStatement){
						element.addContent(devStatement);
					}
				}
			}
		}
		
		return element;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toXML()
	 */
	@Override
	public Element toXML() {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readXML(org.jdom2.Element)
	 */
	@Override
	public int readXML(Element element) throws ModelException {
		// TODO Auto-generated method stub
		return 0;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYin(org.jdom2.Element)
	 */
	@Override
	public int readYin(Element element) throws ModelException {
		if (null == element){
			return MODELELEMENT_OK;
		}
		
		//����
		if (element.getName().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)){
			Element text = element.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
			if (null == text){
				return MODELELEMENT_FAIL;
			}
			this.setDescription(text.getText());
		}
	    //reference		
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_REFERENCE)){
			
			Element text = element.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
			if (null == text){
				return MODELELEMENT_FAIL;
			}
			this.setReference(text.getText());
		}
		else if (element.getName().equals(YangKeyword.DEVIATE.getKeyword())){
			Deviate dev = (Deviate) ModelElement.parseYin(newSubEnv(), element);
			this.addDeviate(dev);
		}
		return MODELELEMENT_OK;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYANG(com.netscenery.yang.YangStatement)
	 */
	@Override
	public int readYANG(YangStatement statement) throws YangParserException, ModelException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		
		String value = statement.getArgument();
		//����
		if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)){
			this.setDescription(value);
		}
	    //reference
		else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_REFERENCE)){
			this.setReference(value);
		}
		else if (statement.getKeyword().equals(YangKeyword.DEVIATE.getKeyword())){
			Deviate dev = (Deviate) ModelElement.parseYANG(newSubEnv(), statement);
			addDeviate(dev);
		}
		return MODELELEMENT_OK;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#isFieldMandatory(java.lang.String)
	 */
	@Override
	public boolean isFieldMandatory(String field) {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#getMapInfo()
	 */
	@Override
	public MapInfo getMapInfo() throws SecurityException, NoSuchMethodException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}

}
